package com.bjy.qa.agent.transport.command;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.bjy.qa.agent.exception.MyException;
import com.bjy.qa.agent.model.KeyValueStore;
import com.bjy.qa.agent.response.Response;
import com.bjy.qa.agent.tools.SpringTool;
import com.bjy.qa.agent.transport.database.DataBaseConf;
import com.bjy.qa.agent.transport.redis.RedisRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Redis 执行器
 */
public class RedisStepCommand extends ExecuteCommand {
    protected static final Logger logger = LoggerFactory.getLogger(HttpExecuteCommand.class);

    List<KeyValueStore> paramList;
    private static final DataBaseConf dataBaseConf; // 数据库配置

    static {
        dataBaseConf = SpringTool.getBean(DataBaseConf.class);
        logger.info("Redis 配置信息：{}", dataBaseConf);
    }

    /**
     * 构造函数
     * @param resultId 运行结果 id
     * @param caseId 用例 id
     * @param ic 迭代次数（iteration count）
     * @param desc 用例描述
     */
    public RedisStepCommand(String resultId, String caseId, String ic, String desc) {
        super(resultId, caseId, ic, desc);
    }

    @Override
    public Response execute(List<KeyValueStore> paramList) {
        this.paramList = paramList;

        String sql = getSql(paramList);
        String driverClass = getDriverClass(paramList);
        String url = getUrl(paramList);
        String port = getPort(paramList);
        String db = getDB(paramList);
        String password = getPassword(paramList);
        try {
            if (dataBaseConf.getDebug()) {
                logger.info("redis command 「sql={}」 开始执行...", sql);
            }
            RedisRunner redisRunner = getRedisUtil(driverClass, url, port, db, password);
            List ret = redisRunner.execute(sql);
            String resultJson = getExpectJson(ret);

            Response response = new Response(resultJson, null);
            if (dataBaseConf.getDebug()) {
                logger.info("redis command 「sql={}」 执行完成, 「result={}」", new Object[]{sql, response.getBody().toString()});
            }
            return response;
        } catch (Exception e) {
            String message = String.format("数据库步骤 执行错误, sql=「%s」", new Object[]{sql});
            this.logger.error(message, e);
            throw new MyException(String.format("数据库步骤 执行错误, sql=「%s」. %s", new Object[]{sql, e.getMessage()}));
        }
    }

    private String getSql(List<KeyValueStore> processedParams) {
        return getValueByKey("sql", processedParams);
    }

    private String getDriverClass(List<KeyValueStore> processedParams) {
        return getValueByKey("driverClass", processedParams);
    }

    private String getUrl(List<KeyValueStore> processedParams) {
        return getValueByKey("url", processedParams);
    }

    private String getPort(List<KeyValueStore> processedParams) {
        return getValueByKey("port", processedParams);
    }

    private String getDB(List<KeyValueStore> processedParams) {
        return getValueByKey("db", processedParams);
    }

    private String getPassword(List<KeyValueStore> processedParams) {
        return getValueByKey("password", processedParams);
    }

    private String getValueByKey(String key, List<KeyValueStore> processedParams) {
        for (KeyValueStore kvs : processedParams) {
            if (key.equals(kvs.getName())) {
                return (String) kvs.getValue();
            }
        }
        return null;
    }

    protected RedisRunner getRedisUtil(String driverClass, String url, String port, String db, String password) {
        return new RedisRunner(driverClass, url, port, db, password);
    }

    private String getExpectJson(List<Map<String, Object>> query) {
        if ((query == null) || (query.size() == 0)) {
            return JSON.toJSONString(null);
        }

        Map<String, List> ret = new HashMap<>();
        ret.put("ret", query);
        String expectJson = JSON.toJSONString(ret, new SerializerFeature[]{SerializerFeature.WriteMapNullValue});
        return expectJson;
    }

    @Override
    public String toReportInfo() {
        return String.format("在数据库 %s 上执行 SQL: %s", getUrl(this.paramList), getSql(this.paramList));
    }
}
